<?php

declare(strict_types=1);

namespace app;

use Exception;
use think\facade\Db;
use think\response\Json;

/**
 * API接口基类
 * 提供通用的数据查询方法
 * Class ApiController
 * @package app
 */
class ApiController extends BaseController
{
    protected string $module = '';       // 模块名称
    protected string $controller = '';   // 控制器名称
    protected string $action = '';       // 方法名称
    protected string $requestPath = '';
    protected array $prohibitAccessArr = [
        'executeInTransaction',
    ]; //禁止访问的方法
    protected array $params = [];        // 请求参数
    protected string|int|array $id = '0';               // 主键ID
    protected mixed $data = [];          // 结果集
    protected int $count = 0;  //总数量
    protected mixed $model = '';        // 模型
    protected mixed $validate = '';     // 验证器


    // 初始化

    /**
     * @throws MyException|Exception
     */
    protected function initialize(): void
    {
        //获取访问模块：控制器：方法
        $hierarchical_directory = getConfigs('system_config.hierarchical_directory');
        if(!empty($hierarchical_directory)){
            $this->requestPath = ltrim(request()->baseUrl(),$hierarchical_directory);
        }else{
            $this->requestPath = request()->baseUrl();
        }

        [$this->module, $this->controller, $this->action] = explode('/',$this->requestPath);

        if (in_array($this->action, $this->prohibitAccessArr)) {
            myException('禁止访问');
        }
        $this->params = $this->request->param();
        if ( ! empty($this->params['id'])) {
            $this->id = $this->params['id'];
        }
        unset($this->params['signature']);
        unset($this->params['id']);
    }


    /**
     * 追加禁止访问的方法
     *
     * @param $value
     *
     * @return void
     */
    protected function setProhibitAccessArr($value): void
    {
        if (is_array($value)) {
            $this->prohibitAccessArr = array_merge($this->prohibitAccessArr, $value);
        } else {
            $this->prohibitAccessArr[] = $value;
        }
    }


    /**
     * 在事务中执行操作
     *
     * @param  callable  $callback
     *
     * @return Json
     */
    protected function executeInTransaction(callable $callback): Json
    {
        try {
            Db::startTrans();
            $callback();
            Db::commit();

            return success($this->id);
        } catch (\Exception $e) {
            Db::rollback();

            return error($e->getMessage());
        }
    }
}